from ctypes import windll as ctypeswindll;
def is_admin():
    try:return ctypeswindll.shell32.IsUserAnAdmin();
    except:return False;
if is_admin():pass;
else:
    ctypeswindll.shell32.ShellExecuteW(None,"runas", sysexecutable, __file__, None, 1);
    sysexit();
import tkinter as tk;
import tkinter.messagebox;
from tkinter import ttk;
import threading;
from time import sleep as timesleep;
import pyautogui;
from sys import exit as sysexit;
from sys import executable as sysexecutable;
from plyer import notification;
from webbrowser import open_new;
from keyboard import is_pressed as keyboardis_pressed;
stop = False;
window_top = False;
program_closes = True;
no_notice = False;
last_start_key = "ctrl+k";
last_stop_key = "ctrl+t";
pyautogui.PAUSE = 0;
value = 0;
def val(number):
    global value;
    value = number;
def thread_wait_press():
    global stop;
    if check_hotkey_get.get() == "开启":
        print(1)
        while keyboardis_pressed(stop_key_get.get()) == False:
            pass;timesleep(0.01);
    stop = True;
    print(10)
def thread_click_number():
    global stop,click_number;
    while stop != True:
        timesleep(1.01);
        if stop != True:#这里是防止用户在等待的时间就停止
            if combo_selected.get() == "长按左键" or combo_selected.get() == "长按右键":
                lb_click_count.config(bg="green",text="长按无次数");
            else:
                lb_click_count.config(bg="green",text="每秒" + combo_selected.get() + "次数："+str(click_number));
        click_number = 0;
def func_start_key_lost_focus():
    global last_start_key;
    start_key_get.set(start_key_get.get().replace(" ",""));
    try:
        keyboardis_pressed(start_key_get.get());start_key_get.set(start_key_get.get().lower());
        if start_key_get.get() != stop_key_get.get():
            last_start_key = start_key_get.get();
        else:
            tkinter.messagebox.showerror("错误","你输入的停止键和启动键重复，请重新输入");
            start_key_get.set(last_start_key);
    except:
        tkinter.messagebox.showerror("错误","你输入的数值不符合要求，请重新输入");
        start_key_get.set(last_start_key);
def func_stop_key_lost_focus():
    global last_stop_key;
    stop_key_get.set(stop_key_get.get().replace(" ",""));
    try:
        keyboardis_pressed(stop_key_get.get());stop_key_get.set(stop_key_get.get().lower());
        if stop_key_get.get() != start_key_get.get():
            last_stop_key = stop_key_get.get();
        else:
            tkinter.messagebox.showerror("错误","你输入的停止键和启动键重复，请重新输入");
            stop_key_get.set(last_stop_key);
    except:
        tkinter.messagebox.showerror("错误","你输入的数值不符合要求，请重新输入");
        stop_key_get.set(last_stop_key);
def func_detect_presses():
    global sleep_time,entered,stop,click_number,combo_selected;
    while program_closes:
        if check_hotkey_get.get() == "开启":
            try:
                while not keyboardis_pressed(start_key_get.get()):pass;timesleep(0.01);func_judgment();
            except:
                while True:
                    try:keyboardis_pressed(start_key_get.get());break;
                    except:timesleep(0.1);
                continue;








        stop = False;
        try:
            sleep_time=float(entered.get());
        except:
            if combo_selected.get() != "长按左键" and combo_selected.get() != "长按右键":
                tkinter.messagebox.showerror("1错误","你输入的数值不符合要求，请重新输入");
                continue;
        else:
            sleep_time=0;
        if not sleep_time <= 1.0 or not sleep_time >= 0.0:
            tkinter.messagebox.showerror("2错误","你输入的数值不符合要求，请重新输入");
        elif combo_selected.get() == "":
            tkinter.messagebox.showerror("3错误","你没有选择点击的键");
        else:
            if not no_notice:
                notification.notify(title = "连点器",message = "即将开始",app_icon = None,timeout = 10)
            if combo_selected.get() == "长按左键" or combo_selected.get() == "长按右键":
                lb_click_count.config(bg="grey",text="长按无次数");
            else:
                lb_click_count.config(bg="grey",text="每秒" + combo_selected.get() + "次数：即将开始点击");
            thread_wait = threading.Thread(target=thread_wait_press);
            thread_click_number_1 = threading.Thread(target=thread_click_number);
            click_number = 0;
            thread_wait.start();
            thread_click_number_1.start();
            while not stop:
                if combo_selected.get() == "单击左键":
                    pyautogui.click(button="left");
                    timesleep(sleep_time);
                if combo_selected.get() == "单击右键":                                                                                  
                    pyautogui.click(button="right");
                    timesleep(sleep_time);
                if combo_selected.get() == "双击左键":                                                                                  
                    pyautogui.doubleClick(button="left");
                    timesleep(sleep_time);
                if combo_selected.get() == "双击右键":                                                                                  
                    pyautogui.doubleClick(button="right");
                    timesleep(sleep_time);
                if combo_selected.get() == "三击左键":                                                                                  
                    pyautogui.tripleClick(button="left");
                    timesleep(sleep_time);
                if combo_selected.get() == "三击右键":                                                                                  
                    pyautogui.tripleClick(button="right");
                    timesleep(sleep_time);
                if combo_selected.get() == "长按左键":                                                                                  
                    pyautogui.mouseDown(button="left")
                    while not stop:timesleep(0.01);
                    pyautogui.mouseUp(button = 'left');
                if combo_selected.get() == "长按右键":                                                                                  
                    pyautogui.mouseDown(button="right");
                    while not stop:timesleep(0.01);
                    pyautogui.mouseUp(button = 'right');
                click_number = click_number + 1;
            if combo_selected.get() == "长按左键" or combo_selected.get() == "长按右键":
                lb_click_count.config(bg="grey",text="长按无次数");
            else:
                lb_click_count.config(bg="grey",text="每秒" + combo_selected.get() + "次数：当前未连点");
            lb_click_count.config(bg="grey",text="每秒" + combo_selected.get() + "次数：当前未连点");
            if not no_notice:
                notification.notify(title = "连点器",message = "已结束",app_icon = None,timeout = 10);
    sysexit();
def func_top_floor():
    global window,window_top;
    if window_top != True:
        window.attributes('-topmost', 'true');
        window_top = True
    else:
        window.attributes('-topmost', 'false');
        window_top = False
def func_about_exit():
    about_window.destroy();
    window.attributes('-disabled',False);
def window_undisable():
    window.attributes('-disabled',False);
    about_window.destroy();
def individual():
    open_new('https://space.bilibili.com/3493083240991380')
def func_about():
    global about_window,window;
    window.attributes('-topmost', 'false');
    window.attributes('-disabled',True);
    about_window = tk.Tk();
    about_window.title("关于连点器");
    about_window.geometry("150x180");
    about_window.resizable(False,False);
    about_window.attributes("-toolwindow", 2);
    lb_about = tk.Label(about_window,text="鼠标连点器  V2.0.2\n-2023年12月30日-\n本次更新内容：\n1、适配sclqx.top\n-liuqx1234-",justify='left');
    bt_about_update = tk.Button(about_window,text="历史更新记录",command=func_history);
    bt_about_exit = tk.Button(about_window,text="关闭",command=func_about_exit);
    bt_individual = tk.Button(about_window,text="B站个人主页",command=individual)
    lb_about.grid(row=0,column=0,padx=(0,0),pady=0,columnspan=2);
    bt_about_exit.grid(row=1,column=1,padx=(0,0),pady=0);
    bt_about_update.grid(row=1,column=0,padx=(0,0),pady=0);
    bt_individual.grid(row=2,column=0,padx=(0,0),pady=2)
    about_window.protocol("WM_DELETE_WINDOW",window_undisable)
    about_window.mainloop();
def func_history(): 
    open_new("https://sclqx.top/liandianqi/history_update.html")
def window_exit():
    global program_closes;
    window.destroy();
    program_closes = False;
    sysexit(0);
def func_notice_on_off():
    global no_notice;
    if check_no_notice_value.get() == "禁用":
        no_notice = True;
    else:
        no_notice = False;
def func_judgment():
    if combo_selected.get() == "长按左键" or combo_selected.get() == "长按右键":
        text.grid_forget();
        lb.config(text="长按模式下不能选择");
        lb.grid(columnspan=2);
        click_interval.config(padx=104);
        lb_click_count.config(bg="grey",text="长按无次数");
    else:
        lb.config(text="输入范围0-60间，支持小数");
        lb.grid(columnspan=1);
        text.grid(row=0,column=1,padx=(0,0),pady=0,sticky="W");
        click_interval.config(padx=69);
        lb_click_count.config(bg="grey",text="每秒" + combo_selected.get() + "次数：当前未连点");
def func_hotkey_start():
    global start_key,stop_key;
    if check_hotkey_get.get() == "开启":
        start_key.configure(state='normal');
        stop_key.configure(state='normal');
    else:
        start_key.configure(state='disabled');
        stop_key.configure(state='disabled');
window = tk.Tk();
window.title("连点器");
window.geometry("800x600");
window.resizable(False,False);
window.protocol("WM_DELETE_WINDOW",window_exit);
top_floor = False;
top = tk.Menu(window);
top.add_cascade(label="关于",command=func_about);
window.config(menu=top);

click_interval = tk.LabelFrame(window,text="点击间隔",padx=69, pady=5);
click_type = tk.LabelFrame(window,text="点击类型",padx=80, pady=5);
startup_conditions = tk.LabelFrame(window,text="启动连点条件");

lb = tk.Label(click_interval,text="输入范围0-60间，支持小数",fg="black");
entered = tkinter.StringVar();
text = tk.Entry(click_interval,width=4,textvariable=entered);

combo_selected = tkinter.StringVar();
combo = ttk.Combobox(click_type, textvariable=combo_selected,width=7);
combo.configure(state="readonly");
combo["value"] = ("单击左键","单击右键","双击左键","双击右键","三击左键","三击右键","长按左键","长按右键");
combo_selected.set("单击左键");
lb_2 = tk.Label(click_type,text="选择点击类型：",fg="black");

tk.Label(startup_conditions,text=" ",fg="black").grid(row=0,column=0,padx=(0,0),pady=0,sticky="W");
check_hotkey_get = tk.StringVar();
check_hotkey = ttk.Checkbutton(startup_conditions,text="键盘启动",variable=check_hotkey_get,onvalue="开启",offvalue="不开启",command=func_hotkey_start);
tk.Label(startup_conditions,text="开始按键：",fg="black").grid(row=1,column=1,padx=(0,0),pady=0,sticky="W");
start_key_get = tk.StringVar();
start_key = tk.Entry(startup_conditions,width=20,textvariable=start_key_get);
start_key.bind('<FocusOut>', lambda event, e=start_key_get: func_start_key_lost_focus());
tk.Label(startup_conditions,text="结束按键：",fg="black").grid(row=2,column=1,padx=(0,0),pady=0,sticky="W");
stop_key_get = tk.StringVar();
stop_key = tk.Entry(startup_conditions,width=20,textvariable=stop_key_get);
stop_key.bind('<FocusOut>', lambda event, e=stop_key_get: func_stop_key_lost_focus());
start_key_get.set("ctrl+k");
stop_key_get.set("ctrl+t");
check_hotkey_get.set("开启");
#-----
check_mouse_get = tk.StringVar();
check_mouse = ttk.Checkbutton(startup_conditions,text="鼠标启动",variable=check_mouse_get,onvalue="开启",offvalue="不开启",command=func_notice_on_off);
tk.Label(startup_conditions,text="请选择触发的键：").grid(row=4,column=1,padx=(0,0),pady=0,sticky="W",columnspan=2);
right_click_without_get = tk.StringVar();
right_click_without = ttk.Checkbutton(startup_conditions,text="鼠标右键反点（关闭后右键不受连点器影响）",variable=right_click_without_get,onvalue="开启",offvalue="不开启",command=func_notice_on_off);
left_click_without_get = tk.StringVar();
left_click_without = ttk.Checkbutton(startup_conditions,text="鼠标左键（关闭后左键不受连点器影响）",variable=left_click_without_get,onvalue="开启",offvalue="不开启",command=func_notice_on_off);
#-----
check_hotkey.grid(row=0,column=0,padx=(0,0),pady=0,sticky="W",columnspan=2);
start_key.grid(row=1,column=2,padx=(0,0),pady=0,sticky="W");
stop_key.grid(row=2,column=2,padx=(0,0),pady=0,sticky="W");
check_mouse.grid(row=3,column=0,padx=(0,0),pady=0,sticky="W");
right_click_without.grid(row=5,column=1,padx=(0,0),pady=0,sticky="W",columnspan=2);
left_click_without.grid(row=6,column=1,padx=(0,0),pady=0,sticky="W",columnspan=2);
tk.Label(startup_conditions,text="如果你两个都不选，那么你将无法启动连点",fg="black").grid(row=7,column=0,padx=(0,0),pady=0,sticky="W",columnspan=3);

lb_click_count = tk.Label(window,text="每秒单击左键次数：当前未连点",bg="grey",font=("微软雅黑", 10));
check_top_set_value = tk.StringVar();
check_top_window=ttk.Checkbutton(window,text="置顶窗口",variable=check_top_set_value,onvalue="置顶",offvalue="不置顶",command=func_top_floor);
lb_prompt = tk.Label(window,text="提示：如果是长按，请忽略点击间隔输入框；如\n果选择的是双击/三击，每秒点击次数就指的是双\n击/三击了多少下；CPU越好，点击次数越多");
check_no_notice_value = tk.StringVar();
check_no_notice = ttk.Checkbutton(window,text="禁用已开始已结束通知",variable=check_no_notice_value,onvalue="禁用",offvalue="不禁用",command=func_notice_on_off);
lb.grid(row=0,column=0,padx=(0,0),pady=0,sticky="W");
text.grid(row=0,column=1,padx=(0,0),pady=0,sticky="W");
combo.grid(row=0,column=1,padx=(0,0),pady=0,sticky="W");
lb_2.grid(row=0,column=0,padx=(0,0),pady=0,sticky="W");
click_type.grid(row=0,column=0,padx=(0,0),pady=0,columnspan=2,sticky="W");
click_interval.grid(row=1,column=0,padx=(0,0),pady=0,columnspan=2,sticky="W");
check_top_window.grid(row=2,column=0,padx=(0,0),pady=0);
check_no_notice.grid(row=2,column=1,padx=(0,0),pady=0)
lb_click_count.grid(row=3,column=0,padx=(0,0),columnspan=2);
lb_prompt.grid(row=5,column=0,padx=(0,0),columnspan=2);
startup_conditions.grid(row=6,column=0,padx=(0,0),columnspan=2);
detect_presses = threading.Thread(target=func_detect_presses);
detect_presses.start();#用多线程判断用户是否按下ctrl+k
tk.mainloop();